<!DOCTYPE html>
<meta charset="utf-8">
<style>
    .axis--grid .domain {
        fill: #ddd;
        stroke: none;
    }

    .axis--x .domain,
    .axis--grid .tick line {
        stroke: #fff;
    }

    .axis--grid .tick--minor line {
        stroke-opacity: .5;
    }
</style>

<body>
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <script>

        var margin = { top: 200, right: 40, bottom: 200, left: 40 },
            width = 960 - margin.left - margin.right,
            height = 500 - margin.top - margin.bottom;

        var x = d3.scaleTime()
            .domain([new Date(2013, 7, 1), new Date(2013, 7, 15) - 1])
            .rangeRound([0, width]);

        var svg = d3.select("body").append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

        svg.append("g")
            .attr("class", "axis axis--grid")
            .attr("transform", "translate(0," + height + ")")
            .call(d3.axisBottom(x)
                .ticks(d3.timeHour, 12)
                .tickSize(-height)
                .tickFormat(function () { return null; }))
            .selectAll(".tick")
            .classed("tick--minor", function (d) { return d.getHours(); });

        svg.append("g")
            .attr("class", "axis axis--x")
            .attr("transform", "translate(0," + height + ")")
            .call(d3.axisBottom(x)
                .ticks(d3.timeDay)
                .tickPadding(0))
            .attr("text-anchor", null)
            .selectAll("text")
            .attr("x", 6);

        svg.append("g")
            .attr("class", "brush")
            .call(d3.brushX()
                .extent([[0, 0], [width, height]])
                .on("brush", brushed));

        function brushed() {
            if (d3.event.sourceEvent.type === "brush") return;
            var d0 = d3.event.selection.map(x.invert),
                d1 = d0.map(d3.timeDay.round);

            // If empty when rounded, use floor instead.
            if (d1[0] >= d1[1]) {
                d1[0] = d3.timeDay.floor(d0[0]);
                d1[1] = d3.timeDay.offset(d1[0]);
            }

            d3.select(this).call(d3.event.target.move, d1.map(x));
        }

    </script>